package com.xqq.service;

import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.opencsv.CSVReader;
import com.xqq.dao.ConflictEventDAO;
import com.xqq.entity.ConflictEventDO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import static com.xqq.utils.Constants.DISORDER_TYPE_MAP;

@Service
public class CSVService {

    @Resource
    private ConflictEventDAO conflictEventDAO;

    @Transactional
    public void readCsvAndSaveToDatabase(String filePath, boolean isAdd) {
//        SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MMM-yy", Locale.ENGLISH);
//        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH);
        long startTime = System.currentTimeMillis();
        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, Integer> subEventTypeHashMap = new HashMap<>();
        Map<String, Integer> eventTypeHashMap = new HashMap<>();
        if (!isAdd) {
            conflictEventDAO.remove(new LambdaQueryWrapper<>());
        }
        System.out.println("ready to save .....");
        try (CSVReader reader = new CSVReader(new FileReader(filePath.trim()))) {
            List<String[]> records = reader.readAll();
            List<ConflictEventDO> events = new ArrayList<>();
            for (String[] record : records.subList(1, records.size())) { // Skip header
                ConflictEventDO.Builder builder = new ConflictEventDO.Builder();
                String eventType = record[5];
                String subEventType = record[6];
                String eventDate = outputFormat.format(inputFormat.parse(record[1]));
//                subEventTypeHashMap.put(subEventType,subEventTypeHashMap.getOrDefault(subEventType,0)+1);
//                eventTypeHashMap.put(eventType,eventTypeHashMap.getOrDefault(eventType,0)+1);
                builder.eventIdCnty(record[0])
                        .eventDate(LocalDate.parse(eventDate))
                        .year(Integer.parseInt(record[2].isEmpty() ? "0" : record[2]))
                        .timePrecision(Integer.parseInt(record[3].isEmpty() ? "0" : record[3]))
                        .disorderType(record[4])
                        .eventType(eventType)
                        .eventTypeZh(DISORDER_TYPE_MAP.get(eventType))
                        .subEventType(subEventType)
                        .actor1(record[7])
                        .assocActor1(record[8])
//                        .inter1(Integer.parseInt(record[9].isEmpty() ? "0" : record[9]))
                        .actor2(record[10])
                        .assocActor2(record[11])
//                        .inter2(Integer.parseInt(record[12]))
//                        .interaction(Integer.parseInt(record[13].isEmpty() ? "0" : record[13]))
                        .civilianTargeting(record[14])
                        .iso(Integer.parseInt(record[15].isEmpty() ? "0" : record[15]))
                        .region(record[16])
                        .country(record[17])
                        .admin1(record[18])
                        .admin2(record[19])
                        .admin3(record[20])
                        .location(record[21])
                        .latitude(Double.parseDouble(record[22]))
                        .longitude(Double.parseDouble(record[23]))
                        .geoPrecision(Integer.parseInt(record[24]))
                        .source(record[25])
                        .sourceScale(record[26])
                        .notes(record[27])
                        .fatalities(Integer.parseInt(record[28].isEmpty() ? "0" : record[28]))
                        .tags(record[29])
                        .timestamp(Long.parseLong(record[30]));
                ConflictEventDO conflictEventDO = builder.build();
                events.add(conflictEventDO);
            }
            ListUtil.reverse(events);
            boolean b = conflictEventDAO.saveBatch(events);
            if (b) {
                System.out.println("Successfully saved " + events.size() + " records to the database.");
            }
            subEventTypeHashMap.entrySet().forEach(System.out::println);
            System.out.println("================================");
            eventTypeHashMap.entrySet().forEach(System.out::println);
            System.out.println("耗时" + (System.currentTimeMillis() - startTime) / 1000 + "s");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Transactional
    public void readCsvAndAddToDatabase(String filePath) {
//        SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MMM-yy", Locale.ENGLISH);
//        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH);
        long startTime = System.currentTimeMillis();
        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, Integer> subEventTypeHashMap = new HashMap<>();
        Map<String, Integer> eventTypeHashMap = new HashMap<>();
        //先读取数据库找到最新一天的数据的天
        ConflictEventDO one = conflictEventDAO.lambdaQuery().orderByDesc(ConflictEventDO::getEventDate).last("limit 1").one();
        LocalDate lastEventDate = null;
        if (one != null) {
            lastEventDate = one.getEventDate();
            System.out.println("lastEventDate:" + lastEventDate);
            conflictEventDAO.remove(new LambdaQueryWrapper<ConflictEventDO>().eq(ConflictEventDO::getEventDate, lastEventDate));
        }
        System.out.println("ready to save .....");
        try (CSVReader reader = new CSVReader(new FileReader(filePath.trim()))) {
            List<String[]> records = reader.readAll();
            List<ConflictEventDO> events = new ArrayList<>();
            for (String[] record : records.subList(1, records.size())) { // Skip header
                ConflictEventDO.Builder builder = new ConflictEventDO.Builder();
                String eventType = record[5];
                String subEventType = record[6];
                String eventDate = outputFormat.format(inputFormat.parse(record[1]));
                if (lastEventDate != null && lastEventDate.isAfter(LocalDate.parse(eventDate))) {
                    ListUtil.reverse(events);
                    boolean b = conflictEventDAO.saveBatch(events);
                    if (b) {
                        System.out.println("Successfully add " + events.size() + " records to the database.");
                    }
                    subEventTypeHashMap.entrySet().forEach(System.out::println);
                    System.out.println("================================");
                    eventTypeHashMap.entrySet().forEach(System.out::println);
                    System.out.println("耗时" + (System.currentTimeMillis() - startTime) / 1000 + "s");
                    return;
                }
//                subEventTypeHashMap.put(subEventType,subEventTypeHashMap.getOrDefault(subEventType,0)+1);
//                eventTypeHashMap.put(eventType,eventTypeHashMap.getOrDefault(eventType,0)+1);
                builder.eventIdCnty(record[0])
                        .eventDate(LocalDate.parse(eventDate))
                        .year(Integer.parseInt(record[2].isEmpty() ? "0" : record[2]))
                        .timePrecision(Integer.parseInt(record[3].isEmpty() ? "0" : record[3]))
                        .disorderType(record[4])
                        .eventType(eventType)
                        .eventTypeZh(DISORDER_TYPE_MAP.get(eventType))
                        .subEventType(subEventType)
                        .actor1(record[7])
                        .assocActor1(record[8])
//                        .inter1(Integer.parseInt(record[9].isEmpty() ? "0" : record[9]))
                        .actor2(record[10])
                        .assocActor2(record[11])
//                        .inter2(Integer.parseInt(record[12]))
//                        .interaction(Integer.parseInt(record[13].isEmpty() ? "0" : record[13]))
                        .civilianTargeting(record[14])
                        .iso(Integer.parseInt(record[15].isEmpty() ? "0" : record[15]))
                        .region(record[16])
                        .country(record[17])
                        .admin1(record[18])
                        .admin2(record[19])
                        .admin3(record[20])
                        .location(record[21])
                        .latitude(Double.parseDouble(record[22]))
                        .longitude(Double.parseDouble(record[23]))
                        .geoPrecision(Integer.parseInt(record[24]))
                        .source(record[25])
                        .sourceScale(record[26])
                        .notes(record[27])
                        .fatalities(Integer.parseInt(record[28].isEmpty() ? "0" : record[28]))
                        .tags(record[29])
                        .timestamp(Long.parseLong(record[30]));
                ConflictEventDO conflictEventDO = builder.build();
                events.add(conflictEventDO);
            }
            ListUtil.reverse(events);
            boolean b = conflictEventDAO.saveBatch(events);
            if (b) {
                System.out.println("Successfully saved " + events.size() + " records to the database.");
            }
            subEventTypeHashMap.entrySet().forEach(System.out::println);
            System.out.println("================================");
            eventTypeHashMap.entrySet().forEach(System.out::println);
            System.out.println("耗时" + (System.currentTimeMillis() - startTime) / 1000 + "s");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
